昨天我們已經實作了登入和註冊API,並了解JWT整個運作過程。
接著我們要來開發User相關的API和auth middleware開發
在controllers
資料夾底下建立users-controller.js
//users-controller.js
const HttpError = require('../models/http-error');
const User = require('../models/User'); //記得引入User model
//取得使用者資料
exports.getUserProfile = async (req, res) => {
try {
const userId = req.params.userId;
const user = await User.findById(userId);
if (!user) {
return next(new HttpError('查無此使用者', 404));
}
// 取得使用者資料(記得不可以回傳密碼)
const userProfile = {
fullName: user.fullName,
email: user.email,
joinDate: user.joinDate,
bio: user.bio,
profileImage: user.profileImage
};
res.json(userProfile);
} catch (error) {
next(new HttpError('Server error', 500));
}
};
//更新使用者資料
exports.updateUserProfile = async (req, res) => {
try {
const userId = req.params.userId;
const { fullName, password, bio, profileImage } = req.body;
const updatedData = {
...(fullName && { fullName }),
...(password && { password }),
...(bio && { bio }),
...(profileImage && { profileImage })
};
const updatedUser = await User.findByIdAndUpdate(userId, updatedData, { new: true });
if (!updatedUser) {
return next(new HttpError('查無此使用者', 404));
}
const updatedProfile = {
fullName: updatedUser.fullName,
email: updatedUser.email,
joinDate: updatedUser.joinDate,
bio: updatedUser.bio,
profileImage: updatedUser.profileImage
};
res.json(updatedProfile);
} catch (error) {
next(new HttpError('Server error', 500));
}
};
接著在routes
資料夾底下建立users-routes.js
,並把剛剛建立user-controller.js
引入
//users-routes.js
const express = require('express');
const router = express.Router();
const userControllers = require('../../controllers/users-controller');
//@router GET api/users/:userId/profile
//@desc GET 取得使用者資訊
//@access Public
router.get('/:userId/profile', userControllers.getUserProfile);
//@router PUT api/users/:userId/profile
//@desc PUT 修改使用者資料
//@access Public
router.put('/:userId/profile', userControllers.updateUserProfile);
module.exports = router;
最後在server.js
引入users-routes.js
//server.js
const express = require('express');
const connectDB = require('./config/db');
const app = express();
const bodyParser = require('body-parser');
const users = require('./routes/api/users-route'); //引入users-routes.js
const auth = require('./routes/api/auth-route');
const posts = require('./routes/api/posts-route');
connectDB();
app.use(bodyParser.json());
app.use('/api/users', users);
...(略)
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
更新使用者資料
取得使用者資料
昨天我們有介紹authorization(授權)是什麼,並且也實作了JWT(JSON Web Token)。
❓稍微再複習一下token是什麼
在前後端溝通時,token 就是前後端溝通用的憑證。前端若要和後端伺服器請求任何資料時,都必須要在發出去的請求中帶入這個 token 憑證,如果沒有攜帶憑證,或是憑證有誤的話,伺服器都不會回應請求。這個機制也是避免有未經授權的訪問和資料的竄改和偽造。
那當我們呼叫API時,該如何去驗證這個API有沒有攜帶合法憑證;若有攜帶合法憑證又該如何授權?
👉這時就要建立Auth middleware
,來為我們檢驗這個API是否有攜帶或有合法的憑證
🛠️運作概念如下:
如果認證或授權失敗,Auth middleware 通常會直接回應錯誤。若認證成功,它會解析出的使用者資訊附加到請求上,然後將控制權傳遞給下一個中介軟體或路由處理程式。
建立middleware
資料夾,並在底下新增auth.js
檔案
//auth.js
const jwt = require('jsonwebtoken');
const config = require('config'); //存取設置的私鑰
module.exports = function(req, res, next) {
//從請求標頭中提取JWT(JSON Web Token)
const bearerHeader = req.header('Authorization');
// 如果沒有則回傳錯誤
if(!bearerHeader){
return res.status(401).json({msg: 'No token, authorization denied'});
}
const bearer = bearerHeader.split(' ');
const token = bearer[1];
//檢驗憑證
try{
//判斷提供的憑證是否有效
const decoded = jwt.verify(token,config.get('jwtSecret'));
// 將解析出來的使用者資訊加到請求上
req.user = decoded.user;
// 轉到下一個middleware或路由處理程式
next();
}
catch(err){
res.status(401).json({msg: '無效的憑證'});
}
}
完成剛剛的auth middleware
後,我們就要在post
和user
api上加上這個中介軟體,避免未經授權的使用者去取得這些敏感資料或者進行非法的操作。
const express = require("express");
const router = express.Router();
const postControllers = require("../../controllers/posts-controller");
const auth = require("../../middleware/auth"); //引入我們剛剛的auth middleware
//@router POST /api/posts
//@desc 新增文章
//@access Public
router.post("/", auth, postControllers.createPost); //在function中間加入auth
//@router GET api/posts/:postId
//@desc 取得單一文章
//@access Public
router.get("/:postId", auth, postControllers.getPost);
//@router PUT /api/posts/:postId
//@desc 更新文章
//@access Public
router.put("/:postId", auth, postControllers.updatePost);
//@router DELETE api/posts
//@desc 刪除文章
//@access Public*/
router.delete("/:postId",auth,postController.deletePost);
module.exports = router;
const express = require('express');
const router = express.Router();
const userControllers = require('../../controllers/users-controller');
const auth = require("../../middleware/auth"); //引入我們剛剛的auth middleware
//@router GET api/users/:userId/profile
//@desc GET 取得使用者資訊
//@access Public
router.get('/:userId/profile', auth, userControllers.getUserProfile);
//@router PUT api/users/:userId/profile
//@desc PUT 修改使用者資料
//@access Public
router.put('/:userId/profile', auth, userControllers.updateUserProfile);
module.exports = router;